import * as Blockly from 'blockly';
import { javascriptGenerator } from 'blockly/javascript';
import { isInAsyncContext } from '../core/utils';

// 为函数块添加异步选项
function addAsyncOptionToFunctionBlocks() {
  const functionBlockTypes = [
    'procedures_defreturn',
    'procedures_defnoreturn',
    'function_block', // 可能的自定义函数块类型
  ];

  functionBlockTypes.forEach((blockType) => {
    if (Blockly.Blocks[blockType] && Blockly.Blocks[blockType].init) {
      const originalInit = Blockly.Blocks[blockType].init;

      Blockly.Blocks[blockType].init = function () {
        originalInit.call(this);

        // 添加异步复选框
        const asyncInput = this.appendDummyInput('ASYNC_INPUT')
          .appendField('异步')
          .appendField(new Blockly.FieldCheckbox(false), 'ASYNC');

        // 将异步选项移到适当位置
        if (this.inputList.indexOf(this.getInput('STACK')) !== -1) {
          this.moveInputBefore('ASYNC_INPUT', 'STACK');
        } else {
          this.moveInputBefore('ASYNC_INPUT', 0);
        }
      };
    }
  });

  // 添加一个验证函数，检查函数定义块中是否有 await 调用
  ['procedures_defreturn', 'procedures_defnoreturn'].forEach((blockType) => {
    Blockly.Blocks[blockType].onchange = function (event: any) {
      // 使用闭包捕获正确的this上下文
      const block = this;

      if (!block || !block.workspace || block.isInFlyout) {
        return; // 不在工作区中或在工具箱中，不需要验证
      }

      // 只有当块被修改或移动时才检查
      if (
        event.type !== Blockly.Events.BLOCK_CHANGE &&
        event.type !== Blockly.Events.BLOCK_MOVE
      ) {
        return;
      }

      const isAsync = block.getFieldValue('ASYNC') === 'TRUE';

      // 如果函数不是异步的，检查它是否包含 await 调用
      if (!isAsync) {
        const containsAwait = block.containsAwaitCall(block);
        if (containsAwait) {
          block.setWarningText('此函数包含 await 调用，但函数未标记为 async');
        } else {
          block.setWarningText(null);
        }
      } else {
        block.setWarningText(null);
      }
    };
  });

  // 添加一个辅助方法来检查块及其子块是否包含 await 调用
  ['procedures_defreturn', 'procedures_defnoreturn'].forEach((blockType) => {
    Blockly.Blocks[blockType].containsAwaitCall = function (block: any) {
      if (!javascriptGenerator) {
        return false;
      }

      try {
        // 获取函数体内的代码
        const functionBody = javascriptGenerator.statementToCode(
          block,
          'STACK'
        );

        // 检查代码中是否包含 await 关键字
        return functionBody.includes('await ');
      } catch (e) {
        console.error('检查await关键字时出错:', e);
        return false;
      }
    };
  });
}

// 为方法定义块添加异步选项
function addAsyncOptionToMethodBlocks() {
  // 假设方法定义块的类型是 'method_definition'
  const originalMethodDefInit = Blockly.Blocks['method_definition']
    ? Blockly.Blocks['method_definition'].init
    : null;

  if (originalMethodDefInit) {
    Blockly.Blocks['method_definition'].init = function () {
      originalMethodDefInit.call(this);

      // 添加异步复选框
      const asyncInput = this.appendDummyInput('ASYNC_INPUT')
        .appendField('异步')
        .appendField(new Blockly.FieldCheckbox(false), 'ASYNC');

      // 将异步选项移到适当位置
      this.moveInputBefore('ASYNC_INPUT', 'STACK');
    };

    // 添加验证函数，检查方法定义块中是否有 await 调用
    ['method_definition'].forEach((blockType) => {
      Blockly.Blocks[blockType].onchange = function (event: any) {
        const block = this;
        if (!block || !block.workspace || block.isInFlyout) {
          return; // 不在工作区中或在工具箱中，不需要验证
        }

        // 只有当块被修改或移动时才检查
        if (
          event.type !== Blockly.Events.BLOCK_CHANGE &&
          event.type !== Blockly.Events.BLOCK_MOVE
        ) {
          return;
        }

        const isAsync = block.getFieldValue('ASYNC') === 'TRUE';

        // 如果方法不是异步的，检查它是否包含 await 调用
        if (!isAsync) {
          // 使用与函数块相同的检查逻辑
          const containsAwait =
            Blockly.Blocks['procedures_defreturn'].containsAwaitCall(block);
          if (containsAwait) {
            block.setWarningText('此方法包含 await 调用，但方法未标记为 async');
          } else {
            block.setWarningText(null);
          }
        } else {
          block.setWarningText(null);
        }
      };
    });
  }
}

// 为函数调用块添加 await 选项
function addAwaitOptionToCallBlocks() {
  const callBlockTypes = [
    'procedures_callreturn',
    'procedures_callnoreturn',
    'function_call_block', // 可能的自定义函数调用块类型
  ];

  callBlockTypes.forEach((blockType) => {
    if (Blockly.Blocks[blockType]) {
      // 保存原始初始化函数
      const originalInit = Blockly.Blocks[blockType].init;

      Blockly.Blocks[blockType].init = function () {
        // 调用原始初始化函数
        if (originalInit) {
          originalInit.call(this);
        }

        // 移除可能存在的旧 AWAIT_INPUT
        if (this.getInput('AWAIT_INPUT')) {
          this.removeInput('AWAIT_INPUT');
        }

        // 添加新的 AWAIT_INPUT，确保字段名称为 'AWAIT'
        const awaitInput = this.appendDummyInput('AWAIT_INPUT')
          .appendField('等待')
          .appendField(new Blockly.FieldCheckbox('FALSE'), 'AWAIT');

        // 将 await 选项移到第一个位置
        this.moveInputBefore('AWAIT_INPUT', 0);

        // 添加自定义的 setValue 方法，确保值被正确设置
        const awaitField = this.getField('AWAIT');
        if (awaitField) {
          const originalSetValue = awaitField.setValue;
          awaitField.setValue = function (newValue: any) {
            console.log('Setting AWAIT value to:', newValue);
            const result = originalSetValue.call(this, newValue);
            console.log('AWAIT value after set:', this.getValue());
            return result;
          };
        }
      };

      // 添加验证逻辑
      Blockly.Blocks[blockType].onchange = function (event: any) {
        // 显式获取块实例
        const block = this;

        if (!block || !block.workspace || block.isInFlyout) {
          return; // 不在工作区中或在工具箱中，不需要验证
        }

        // 只有当块被修改或移动时才检查
        if (
          event.type !== Blockly.Events.BLOCK_CHANGE &&
          event.type !== Blockly.Events.BLOCK_MOVE
        ) {
          return;
        }

        // 使用block而不是this
        const useAwait = block.getFieldValue('AWAIT') === 'TRUE';

        // 使用block而不是this
        if (useAwait && !isInAsyncContext(block)) {
          block.setWarningText('await 只能在异步函数或方法内部使用');
        } else {
          block.setWarningText(null);
        }
      };
    }
  });
}

// 为方法调用块添加 await 选项
function addAwaitOptionToMethodCallBlocks() {
  // 假设方法调用块的类型是 'method_call'
  const originalMethodCallInit = Blockly.Blocks['method_call']
    ? Blockly.Blocks['method_call'].init
    : null;

  if (originalMethodCallInit) {
    Blockly.Blocks['method_call'].init = function () {
      originalMethodCallInit.call(this);

      // 添加 await 复选框
      this.appendDummyInput('AWAIT_INPUT')
        .appendField('等待')
        .appendField(new Blockly.FieldCheckbox(false), 'AWAIT');

      // 将 await 选项移到第一个位置
      this.moveInputBefore('AWAIT_INPUT', 0);
    };

    // 修改方法调用块的onChange事件
    Blockly.Blocks['method_call'].onchange = function (event: any) {
      const block = this;
      if (!block || !block.workspace || block.isInFlyout) {
        return; // 不在工作区中或在工具箱中，不需要验证
      }

      // 只有当块被修改或移动时才检查
      if (
        event.type !== Blockly.Events.BLOCK_CHANGE &&
        event.type !== Blockly.Events.BLOCK_MOVE
      ) {
        return;
      }

      const useAwait = block.getFieldValue('AWAIT') === 'TRUE';

      // 使用与函数调用块相同的检查逻辑
      if (useAwait && !isInAsyncContext(block)) {
        block.setWarningText('await 只能在异步函数或方法内部使用');
      } else {
        block.setWarningText(null);
      }
    };
  }
}

// u8ddfu8e2au5f02u6b65u51fdu6570u5757u6ce8u518cu72b6u6001
let asyncFunctionBlocksRegistered = false;

export function registerAsyncFunctionBlocks() {
  // u5982u679cu5df2u7ecfu6ce8u518cu8fc7uff0cu76f4u63a5u8fd4u56de
  if (asyncFunctionBlocksRegistered) {
    console.log('Async function blocks already registered, skipping registration');
    return;
  }
  
  try {
    // u4e3au51fdu6570u5757u6dfbu52a0u5f02u6b65u9009u9879
    addAsyncOptionToFunctionBlocks();

    // u4e3au65b9u6cd5u5b9au4e49u5757u6dfbu52a0u5f02u6b65u9009u9879
    addAsyncOptionToMethodBlocks();

    // u4e3au51fdu6570u8c03u7528u5757u6dfbu52a0awaitu9009u9879
    addAwaitOptionToCallBlocks();

    // u4e3au65b9u6cd5u8c03u7528u5757u6dfbu52a0awaitu9009u9879
    addAwaitOptionToMethodCallBlocks();
    
    // u6807u8bb0u4e3au5df2u6ce8u518c
    asyncFunctionBlocksRegistered = true;
    console.log('Async function blocks registered successfully');
  } catch (error) {
    console.error('Error registering async function blocks:', error);
  }
}
